package com.itheima.easy.handler.aliyun;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.easysdk.kernel.Config;
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
import com.itheima.easy.client.alipay.Factory;
import com.itheima.easy.config.AliPayConfig;
import com.itheima.easy.constant.TradingConstant;
import com.itheima.easy.enums.TradingEnum;
import com.itheima.easy.exception.ProjectException;
import com.itheima.easy.handler.PayNotifyHandler;
import com.itheima.easy.mq.MqMessage;
import com.itheima.easy.pojo.Trading;
import com.itheima.easy.service.ITradingService;
import com.itheima.easy.utils.EmptyUtil;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName AliNotifyHandler.java
 * @Description 支付通知接口
 */
@Component
public class AliPayNotifyHandler implements PayNotifyHandler {

    @Autowired
    AliPayConfig aliPayConfig;

    @Autowired
    ITradingService tradingService;

    @Autowired
    IdentifierGenerator identifierGenerator;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 回调处理
     * @param request http请求对象：支付宝
     * @param httpEntity http请求对象：微信
     * @param enterpriseId
     * @return
     */
    public String notify(HttpServletRequest request, HttpEntity<String> httpEntity,String enterpriseId) {
        //获取参数
        Map<String, String[]> parameterMap = request.getParameterMap();
        Map<String, String> paramMap = new HashMap<>();
        for (String key : parameterMap.keySet()) {
            paramMap.put(key, parameterMap.get(key)[0]);
        }
        try {
            //1、获得支付宝配置
            Config config = aliPayConfig.config(Long.valueOf(enterpriseId));
            //2、配置如果为空，抛出异常
            if (EmptyUtil.isNullOrEmpty(config)){
                throw new ProjectException(TradingEnum.CONFIG_ERROR);
            }
            //3、使用配置
            Factory factory = new Factory();
            factory.setOptions(config);
            //4、验证签名
            boolean verifyResult = factory.Common().verifyNotify(paramMap);
            if (!verifyResult) {
                return "verify sign fail";
            }
            //5、校验支付状态
            if (TradingConstant.ALI_TRADE_SUCCESS.equals(paramMap.get("trade_status"))) {
                Trading trading = tradingService.findTradByTradingOrderNo(Long.valueOf(paramMap.get("out_trade_no")));
                trading.setResultCode(paramMap.get("trade_status"));
                trading.setResultMsg(TradingConstant.ALI_SUCCESS_MSG);
                trading.setResultJson(JSONObject.toJSONString(paramMap));
                trading.setTradingState(TradingConstant.TRADE_SUCCESS);
                tradingService.updateById(trading);

                //发送消息到MQ
                Long messageId = (Long) identifierGenerator.nextId(trading);
                MqMessage mqMessage = MqMessage.builder()
                    .id(messageId)
                    .title("trade-message")
                    .content(JSONObject.toJSONString(trading))
                    .messageType("trade-project-sync")
                    .produceTime(Timestamp.valueOf(LocalDateTime.now()))
                    .sender("system")
                    .build();

                /**
                 * trade-exchange : 交换机的名称
                 * enterpriseId ： 企业id，对应的值为渠道表中的enterprise_id字段的值。
                 *                 每个业务系统都有自己的队列，通过路由key将消息路由到自己的队列
                 *                 此处的路由key就是enterpriseId的值
                 */
                rabbitTemplate.convertAndSend("trade-exchange",enterpriseId,JSON.toJSONString(mqMessage));

                return "success";
            }else {
                return "fail";
            }
        } catch (Exception e) {
            //6、异常返回 fail 给支付宝
            return "fail";
        }
    }
}
